 let _Vue = null

export default class VueRouter {
  constructor(options) {
    this.options = options
    //把options传入的routes解析出来并存储，键是路由地址，值是组件，将来在routeview组件中会根据当前路由地址在routemap中找到对应的组件并渲染
    this.routerMap = {}

    this.mode = options.mode
    //data是响应式对象，它里面有一个current属性，用来记录当前的路由地址，默认情况下当前路由地址是/（根目录）
    this.data = _Vue.observable({
      current: '/'
    })
  }
  // 静态方法，实现vue插件机制,当使用Vue.use注册插件的时候会调用插件类中的静态方法install
  static install(Vue) {
    //判断当前插件是否被安装
    if(VueRouter.install.installed) return
    VueRouter.install.installed = true
    //把vue的构造函数记录到全局变量中
    _Vue = Vue
    //把实例化vue时，传入的router对象挂载到所有的Vue实例上
    _Vue.mixin({
      beforeCreate() {
        if(this.$options.router) {
          _Vue.prototype.$router = this.$options.router
          this.$options.router.init()
        }
      }
    })
  }
  //调用下面三个方法
  init() {
    this.initEvent()
    this.initComponents(_Vue)
    this.createRouteMap()
  }
  //注册popstate事件，用来监听浏览器历史变化
  initEvent() {
    if (this.mode === 'history') {
      window.addEventListener('popstate', () => {
        this.data.current = window.location.pathname
      })
    } else {
      window.addEventListener('load', this.hashChangeHandler.bind(this))
      window.addEventListener('hashchange', this.hashChangeHandler.bind(this))
    }
    
  }
  //初始化routermap属性，把构造函数中传入的路由规则转换成键值对的形式存储到routermap中，键是路由地址，值是对应的组件
  createRouteMap() {
    this.options.routes.forEach(route => {
      this.routerMap[route.path] = route.component
    })
  }
  //创建routerlink和routerview两个组件
  initComponents(Vue) {
    let self = this
    Vue.component('router-link', {
      props: {
        to: String
      },
      render(h) {
        return h('a', {
          attrs: {
            href: `${self.mode === 'history' ? '' : '#'}${this.to}`
          },
          on: {
            click: this.clickHandler
          }
        }, [this.$slots.default])
      },
      methods: {
        clickHandler(e) {
          //三个参数 data:将来触发popstate时，传给popstate时间的时间对象参数；title：网页标题，url当前超链接跳转地址
          if (self.mode === 'history') {
            history.pushState({}, '', this.to)
            this.$router.data.current = this.to
            e.preventDefault()
          }
        } 
      }
    })

    Vue.component('router-view', {
      render(h) {
        const component = self.routerMap[self.data.current]
        return h(component)
      }
    })
  }
  hashChangeHandler() {
    if (!window.location.hash) {
      window.location.hash = '#/'
    } 
    this.data.current = window.location.hash.substr(1)
  }
}